package com.lz.gmall.product.biz.Impl;

import com.lz.gmall.cart.entity.SkuIdAndPrice;
import com.lz.gmall.constant.GmallConstant;
import com.lz.gmall.product.biz.SkuDetailBizService;
import com.lz.gmall.product.entity.SkuInfo;
import com.lz.gmall.product.entity.SpuSaleAttr;
import com.lz.gmall.product.mapper.SkuAttrValueMapper;
import com.lz.gmall.product.mapper.SkuInfoMapper;
import com.lz.gmall.product.mapper.SkuSaleAttrValueMapper;
import com.lz.gmall.product.mapper.SpuSaleAttrMapper;
import com.lz.gmall.product.vo.AttrValueConcatVo;
import com.lz.gmall.product.vo.CategoryViewVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SkuDetailBizServiceImpl implements SkuDetailBizService {

    @Autowired
    private SkuInfoMapper skuInfoMapper;

    @Autowired
    private SpuSaleAttrMapper spuSaleAttrMapper;

    @Autowired
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;

    @Autowired
    private RedissonClient redissonClient;//初始化分布式布隆过滤器，存入redis中，集群多个服务可以使用这一个布隆过滤器


    /**
     * 远程调用接口开发，根据sku的id，获取sku对应的一级，二级，三级产品
     * @param skuId
     * @return
     */
    @Override
    public CategoryViewVo getCategoryViewBySkuId(Long skuId) {
        return skuInfoMapper.getCategoryViewBySkuId(skuId);
    }

    /**
     * 远程调用接口开发，根据sku的id，获取sku的多种信息(SkuInfo)
     * @param skuId
     * @return
     */
    @Override
    public SkuInfo getSkuInfoAndImageById(Long skuId) {
        return skuInfoMapper.getSkuInfoAndImageById(skuId);
    }

    /**
     * 远程调用接口开发,根据sku的id查询skuInfo，从中获取price，因为价格涉及金钱，我们重新查询保证实时性
     * @param skuId
     * @return
     */
    @Override
    public SkuInfo getSkuInfoPriceBySkuId(Long skuId) {
        return skuInfoMapper.selectById(skuId);
    }

    /**
     * 远程调用接口开发,根据sku的id,获取spu的销售属性和销售属性值
     * @param skuId
     * @return
     */
    @Override
    public List<SpuSaleAttr> getSpuSaleAttrListBySkuId(Long skuId) {
        return spuSaleAttrMapper.getSpuSaleAttrListBySkuId(skuId);
    }

    /**
     * 当选择和具体的销售属性值，那么此时就会确定一个SKU
     * 后端将当前SKU所对应的所有的兄弟SKU(包含当前SKU)以JSON的数据格式进行返回
     * 根据skuId，获取spuId,根据spuId获取所有的sku
     * @param skuId
     * @return
     */
    @Override
    public List<AttrValueConcatVo> getAttrValueConcatBySkuId(Long skuId) {
        return skuSaleAttrValueMapper.getAttrValueConcatBySkuId(skuId);
    }

    /**
     * 远程调用，获取所有的商品的skuId，是为了作为分布式缓存使用，存入布隆处理器
     * 防止随机数的穿透
     * @return
     */
    @Override
    public List<Long> getAllStuIdByRpc() {
        List<SkuInfo> skuInfoList = skuInfoMapper.selectList(null);
        List<Long> longList = skuInfoList.stream().map(SkuInfo::getId).collect(Collectors.toList());
        return longList;
    }

    /**
     * 远程调用，获取所有的商品的价格
     * @return
     */
    @Override
    public List<SkuIdAndPrice> getSkuAllPrice() {
        List<SkuInfo> skuInfoList = skuInfoMapper.selectList(null);
        ArrayList<SkuIdAndPrice> priceList = new ArrayList<>();
        for (SkuInfo skuInfo : skuInfoList) {
            SkuIdAndPrice skuIdAndPrice = new SkuIdAndPrice();
            skuIdAndPrice.setSkuId(skuInfo.getId());
            skuIdAndPrice.setPrice(skuInfo.getPrice());
            priceList.add(skuIdAndPrice);
        }
        return priceList;
    }

    /**
     * 初始化布隆过滤器，这样可以不使用远程调用获取所有商品id进行初始化布隆过滤器
     */
    @PostConstruct
    public void initBloomFilter(){

        RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(GmallConstant.REDIS_REDISSON_BLOOM_FILTER);

        if (!bloomFilter.isExists()){
            bloomFilter.tryInit(100000,0.000001);

            List<Long> longList = getAllStuIdByRpc();
            longList.forEach(aLong -> {
                bloomFilter.add(aLong);
            });
        }

        log.info("布隆过滤器初始化完成");
    }
}
